<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\SoftDeletes;

class Partner extends Base
{
    use SoftDeletes;

    const LEVEL_LIMITED = 1;

    const LEVEL_INVITE = 2;

    const LEVEL_MAP = [
        self::LEVEL_LIMITED => '有限合伙人',
        self::LEVEL_INVITE => '邀约合伙人',
    ];

    // 存放 summary model "缓存"
    private $summaryModelCache = [];

    /**
     * 合伙人身份 属于 代理人
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function agent()
    {
        return $this->belongsTo(Agent::class);
    }

    /**
     * 增加 / 减少 业绩和订单数
     * @param $amount
     * @param string $method
     * @param \DateTimeInterface|null $date
     * @param int $numberOfOrder
     */
    public function incrementOrDecrementPerformanceByOrder($amount, $method = 'increment', \DateTimeInterface $date = null, $numberOfOrder = 1)
    {
        $this->{$method}('performance', $amount);
        $this->{$method}('number_of_order', $numberOfOrder);

        // 日月累计
        $date === null && $date = Carbon::now();
        $this->cumulativeDailySummary($date, $method, $amount, $numberOfOrder);
        $this->cumulativeMonthlySummary($date, $method, $amount, $numberOfOrder);
    }

    /**
     * 增加 / 减少 累计收入
     * @param $amount
     * @param string $method
     * @param $date
     */
    public function incrementOrDecrementIncome($amount, $method = 'increment', \DateTimeInterface $date = null)
    {
        $this->{$method}('income', $amount);

        // 日月累计
        $date === null && $date = Carbon::now();
        $this->cumulativeDailySummary($date, $method, 0, 0, $amount);
        $this->cumulativeMonthlySummary($date, $method, 0, 0, $amount);
    }

    /**
     * 增加 / 减少 奖金总和
     * @param $amount
     * @param string $method
     * @param \DateTimeInterface|null $date
     */
    public function incrementOrDecrementReward($amount, $method = 'increment', \DateTimeInterface $date = null)
    {
        $this->{$method}('reward', $amount);

        // 日月累计
        $date === null && $date = Carbon::now();
        $this->cumulativeDailySummary($date, $method, 0, 0, 0, 0, $amount);
        $this->cumulativeMonthlySummary($date, $method, 0, 0, 0, 0, $amount);
    }

    /**
     * 增加 / 减少 佣金
     * @param $amount
     * @param string $method
     * @param \DateTimeInterface|null $date
     */
    public function incrementOrDecrementCommission($amount, $method = 'increment', \DateTimeInterface $date = null)
    {
        $this->{$method}('commission', $amount);

        // 日月累计
        $date === null && $date = Carbon::now();
        $this->cumulativeDailySummary($date, $method, 0, 0, 0, $amount);
        $this->cumulativeMonthlySummary($date, $method, 0, 0, 0, $amount);
    }

    /**
     * 每日汇总
     */
    public function dailySummary()
    {
        return $this->hasMany(IndicatorsDailySummary::class, 'agent_id', 'agent_id');
    }

    /**
     * 累计每日汇总
     * @param \DateTimeInterface $day
     * @param string $method
     * @param int $performance
     * @param int $order
     * @param int $income
     * @param int $commission
     * @param int $reward
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function cumulativeDailySummary(
        \DateTimeInterface $day, $method = 'increment',
        $performance = 0, $order = 0, $income = 0, $commission = 0, $reward = 0
    )
    {
        // 解决多次查询的优化, 这里"缓存"起来
        $dateKey = $day->format('Y-m-d');
        $dateSummaryKey = sprintf('partner_id_%d_type_%d_date_%s', $this->id, SummaryBase::TYPE_PARTNER, $dateKey);
        if (isset($this->summaryModelCache[$dateSummaryKey])) {
            $model = $this->summaryModelCache[$dateSummaryKey];
        } else {
            $model = $this->dailySummary()->firstOrCreate(['type' => SummaryBase::TYPE_PARTNER, 'day' => $dateKey]);
            $this->summaryModelCache[$dateSummaryKey] = $model;
        }

        // 本次请求周期里创建的, 并且是扣减操作, 则不进行扣减, 因为默认值为零, 且不允许负值
        // 出现场景: 后面代理变更为合伙人后, 下面的代理取消订单或者售后时, 找到的当前合伙人去扣减, 但是之前并不是合伙人所以没有业绩统计
        if ($model->wasRecentlyCreated && $method === 'decrement') {
            return $model;
        }

        // 这里的 catch 是上面的场景, 不在本次请求周期创建的, 此时也会扣出负数来, 捕获一下
        try {
            $performance > 0 && $model->{$method}('performance_summary', $performance);
            $order > 0 && $model->{$method}('order_summary', $order);
            $commission > 0 && $model->{$method}('commission_summary', $commission);
            $reward > 0 && $model->{$method}('reward_summary', $reward);
            $income > 0 && $model->{$method}('income_summary', $income);
        } catch (\Exception $e) {
            \Log::info(sprintf('扣减日统计汇总异常, 不影响逻辑: %s (%s [%d])', $e->getMessage(), $e->getFile(), $e->getLine()));
        }

        return $model;
    }

    /**
     * 每月汇总
     */
    public function monthlySummary()
    {
        return $this->hasMany(IndicatorsMonthlySummary::class, 'agent_id', 'agent_id');
    }

    /**
     * 累计每月汇总
     * @param \DateTimeInterface $month
     * @param string $method
     * @param int $performance
     * @param int $order
     * @param int $income
     * @param int $commission
     * @param int $reward
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function cumulativeMonthlySummary(
        \DateTimeInterface $month, $method = 'increment',
        $performance = 0, $order = 0, $income = 0, $commission = 0, $reward = 0
    )
    {
        // 解决多次查询的优化, 这里"缓存"起来
        $dateKey = (int) $month->format('Ym');
        $dateSummaryKey = sprintf('partner_id_%d_type_%d_date_%d', $this->id, SummaryBase::TYPE_PARTNER, $dateKey);
        if (isset($this->summaryModelCache[$dateSummaryKey])) {
            $model = $this->summaryModelCache[$dateSummaryKey];
        } else {
            $model = $this->monthlySummary()->firstOrCreate(['type' => SummaryBase::TYPE_PARTNER, 'month' => $dateKey]);
            $this->summaryModelCache[$dateSummaryKey] = $model;
        }

        // 本次请求周期里创建的, 并且是扣减操作, 则不进行扣减, 因为默认值为零, 且不允许负值
        // 出现场景: 后面代理变更为合伙人后, 下面的代理取消订单或者售后时, 找到的当前合伙人去扣减, 但是之前并不是合伙人所以没有业绩统计
        if ($model->wasRecentlyCreated && $method === 'decrement') {
            return $model;
        }

        // 这里的 catch 是上面的场景, 不在本次请求周期创建的, 此时也会扣出负数来, 捕获一下
        try {
            $performance > 0 && $model->{$method}('performance_summary', $performance);
            $order > 0 && $model->{$method}('order_summary', $order);
            $commission > 0 && $model->{$method}('commission_summary', $commission);
            $reward > 0 && $model->{$method}('reward_summary', $reward);
            $income > 0 && $model->{$method}('income_summary', $income);
        } catch (\Exception $e) {
            \Log::info(sprintf('扣减月统计汇总异常, 不影响逻辑: %s (%s [%d])', $e->getMessage(), $e->getFile(), $e->getLine()));
        }

        return $model;
    }
}
